# statusicon.py -- GUI status icon source

# This file is part of Share-Folder.

# Share-Folder is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# Redshift is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with Share-Folder.  If not, see <http://www.gnu.org/licenses/>.

# Copyright (c) 2010  Guglielmo Saggiorato <astyonax@gmail.com>
# This code is a modified version of the gkt indicator of Redshif
# Thanks to the author for sharing it Jon Lund Steffensen <jonlst@gmail.com>



import os,pickle
#import gettext
import ftpd as f
import pygtk
pygtk.require("2.0")
import gtk, glib
gtk.gdk.threads_init()
from ZeroconfService import ZeroconfService


try:
    import appindicator
except ImportError:
    appindicator = None

from platform import node as pl_node
from multiprocessing import Process
from utils import *
import GUI 

__ver__='0.1'
__author__='Guglielmo Saggiorato <astyonax@gmail.com>'
__doc__='A fast and simple program to share a folder in a LAN'
__website__='http://code.google.com/p/share-folder/'
__app_name__='ShareMe'




class icon(object):
    def __init__(self,cli_directory=None,cli_write=False):
        
        self._running=None
        self.ftp=None
        self.app_name=__app_name__
        self.anon_kw='anonymous'
        self.icon_off=os.path.abspath(os.path.join(os.path.sep.join(__file__.split(os.path.sep)[:-1]),'icon/shareme-off.svg'))
        self.icon_on=os.path.abspath(os.path.join(os.path.sep.join(__file__.split(os.path.sep)[:-1]),'icon/shareme-on.svg'))
        self.bind_port=8001
        self.service=None
        self.cfg_fname=self.app_name+'.pkl'
        self.cfg_fname=os.path.join(os.getenv("HOME"),os.path.join('.config',self.cfg_fname))
        self._load_config()
        if cli_directory:
            self.cli=True
            self.shares=[(True,(self.anon_kw,'',cli_directory,"elradfmw" if cli_write  else 'elr')),]
            print self.shares
        else:
            self.cli=False
        self.n=mynotification("file://"+self.icon_on,self.app_name)
        self.prefs=GUI.FtpGui(self)
        self.prefs.show()
        
    
    @property
    def running(self):
        """ if true the server is ON"""
        return self._running
        
    @running.setter
    def running(self,arg):
        print "running.setter"
        if arg!=self._running:
            self._running=arg
            if arg:
                # running
                self.prefs.GUI_serving()
                self.toggle_item.child.set_text("Stop Sharing")
                if appindicator:
                    self.indicator.set_icon(self.icon_on)
                else:
                    self.status_icon.set_from_file(self.icon_on)
            else:
                #not running
                self.toggle_item.child.set_text("Start Sharing")
                self.prefs.GUI_not_serving()
                if appindicator:
                    self.indicator.set_icon(self.icon_off)
                else:
                    self.status_icon.set_from_file(self.icon_off)
    
    @running.deleter
    def running(self):
        pass
    
    def _first_run(self):
        # create  basic account settings
        # TODO: use default "Public" directory instead of ~
        self.shares=[(True,(self.anon_kw,'',os.path.expanduser('~'),'elr')),]
        self._dump_config()
        
    def _check_config(self):
        # config file is a unique pickle file under $HOME/.configs/app_name
        print self.cfg_fname
        return os.path.exists(self.cfg_fname)
        
    def _load_config(self):
        if not self._check_config():
            self._first_run()
        data=pickle.load(open(self.cfg_fname,'rb'))
        self.shares=data["shares"]
        self.bind_port=data["bind_port"]
        print self.shares
        
    def _dump_config(self):
        if not self.cli:
            data={'shares':self.shares,'bind_port':self.bind_port}
            return pickle.dump(data,open(self.cfg_fname,'wb'))

    def toggle_server(self,widget=None, data=None):
        # this function takes care of spawning the ftp process 
        # and of publishing the Avahi/Bonjour service
    
        if not self.running:
            users=[x[1] for x in filter(lambda x:x[0],self.shares)]
            #self.ftp=Process(target=f.myserver(self.bind_port,users,self))
            self.ftp=f.myserver(self.bind_port,users,self)
            self.ftp()
            self.service = ZeroconfService(name=self.app_name+'@'+pl_node(), port=self.bind_port,  stype="_ftp._tcp")
            
            self.service.publish()
            self.n.show("Shared Folder published")
            self.running= not self.running
        else:
            self.ftp.stop()
            del self.ftp
            self.n.show("Shared Folder no more available","file://"+self.icon_off)
            self.service.unpublish()
            self.running= not self.running

    
        
    def run(self):
        # Internationalisation
        #gettext.bindtextdomain('redshift', defs.LOCALEDIR)
        #gettext.textdomain('redshift')
        #_ = gettext.gettext
        _=lambda w: w
        
        if appindicator:
            # Create indicator
            self.indicator = appindicator.Indicator(self.app_name,
                                               self.icon_off,
                                               appindicator.CATEGORY_APPLICATION_STATUS)
            self.indicator.set_status(appindicator.STATUS_ACTIVE)
        else:
            # Create status icon
            self.status_icon = gtk.StatusIcon()
            self.status_icon.set_from_file(self.icon_off)
            self.status_icon.set_tooltip(self.app_name)

        def destroy_cb(widget, data=None):
            if not appindicator:
                status_icon.set_visible(False)
            if self.running:
                #del self.ftp._target
                self.ftp.stop()

            self._dump_config()
            gtk.main_quit()
            return False
            
        def on_about( widget):
            about = gtk.AboutDialog()
            about.set_program_name(self.app_name)
            about.set_version(__ver__)
            about.set_copyright("(c) "+__author__)
            about.set_comments(__doc__)
            about.set_website(__website__)
            about.set_logo(gtk.gdk.pixbuf_new_from_file(self.icon_on))
            about.run()
            about.destroy()

        # Create popup menu
        status_menu = gtk.Menu()

        self.toggle_item = gtk.MenuItem(_('Share Folder'))
        self.toggle_item.connect('activate', self.toggle_server)
        status_menu.append(self.toggle_item)
        
        gui_item=gtk.MenuItem(_('Preferences'))
        gui_item.connect('activate',self.prefs.show)
        status_menu.append(gui_item)

        #~ label_item=gtk.MenuItem(_('Shared directories'))
        #~ shares_menu=gtk.Menu()
        #~ for share in self.shares:
            #~ share_item=gtk.CheckMenuItem(_(os.path.split(share[1][2])[-1]))
            #~ share_item.set_active(share[0])
            #~ shares_menu.append(share_item)
        #~ label_item.set_submenu(shares_menu)
        #~ status_menu.append(label_item)
        
        about_item=gtk.MenuItem(_('About'))
        about_item.connect('activate',on_about)
        status_menu.append(about_item)
        
        quit_item = gtk.ImageMenuItem(gtk.STOCK_QUIT)
        quit_item.connect('activate', destroy_cb)
        status_menu.append(quit_item)

        if appindicator:
            status_menu.show_all()
            # Set the menu
            self.indicator.set_menu(status_menu)
            self.indicator.connect("scroll-event",self.prefs.hide)
        else:
            def popup_menu_cb(widget, button, time, data=None):
                status_menu.show_all()
                status_menu.popup(None, None, gtk.status_icon_position_menu,
                                  button, time, status_icon)

            # Connect signals for status icon and show
            #status_icon.connect('activate', toggle_cb)
            self.status_icon.connect('popup-menu', popup_menu_cb)
            self.status_icon.set_visible(True)
        gtk.main()

import dbus, dbus.service, dbus.glib
dbus_service='org.filesharing.ShareMe'
dbus_iface='/org/filesharing/ShareMe'

class ExportedService(dbus.service.Object):
    # based on Python Snippets http://aciresnippets.wordpress.com/
    def __init__(self, app):
        self._app = app
        bus_name = dbus.service.BusName(dbus_service, bus = dbus.SessionBus())
        dbus.service.Object.__init__(self, bus_name, dbus_iface)

    @dbus.service.method(dbus_interface=dbus_service)
    def new_shared_dir(self,cli_directory=None,cli_write=False):
        if cli_directory:
            self._app.cli=True
            self._app.shares=[(True,('anonymous','',cli_directory,"elradfmw" if cli_write  else 'elr')),]
        else:
            self._app.cli=False
        if self._app._running:
            self._app.toggle_server()
        self._app.prefs.show()

if __name__=='__main__':
    import argparse
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("-d", dest='d',action='store',default='',metavar="D",help='Directory to share')
    parser.add_argument("-w", dest='w',action='store_true',default=False,help='If set D will be writable (Default:False)')
    args = parser.parse_args()
    
    if args.w and not args.d:
        print "ShareMe" ,"error: option -d is required when using -w"
        exit(1)
    
    # handle single instance check 
    if dbus.SessionBus().request_name(dbus_service) != dbus.bus.REQUEST_NAME_REPLY_PRIMARY_OWNER:
        
        method = dbus.SessionBus().get_object(dbus_service, dbus_iface).get_dbus_method("new_shared_dir")
        method(args.d,args.w)
    else:
        
        t=icon(args.d,args.w)
        service = ExportedService(t)
        t.run()
    
    
   
    
    
